#!/usr/bin/perl

=head1 NAME

AFX::Audit - Audit Execution Script.

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2010 Mikhail Volkov

This file is part of AuditFX.

    AuditFX is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AuditFX is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AuditFX.  If not, see <http://www.gnu.org/licenses/>.
=cut

##############################################################################
# Globals
#

use lib 'lib';
use strict;
use warnings;

use Getopt::Std;

use AFX::ACF;
use AFX::ASF;

## Try to use Process library
eval "use AFX::Process";
if ($@) {
    print "Failed loading AFX::Process library. Error: $@\n";
    die $@;
}

## Execute main script
audit();

##############################################################################
#
# audit()
#
# Command arguments expected are:
# - (-s) site_id     - Site id
# - (-u) units       - Unit's Identifiers
# - (-m) machines    - Machine's Identifiers
# - (-t) templates   - Template's Identifiers
# - (-d) daemon      - Daemon's daily/weekly
# - (-D)             - Debug mode
# - (-x)             - Noprompt mode
# - (-X)             - Suppress N/A within ARF

sub audit {

## Get options
    getopts( "XhxDs:d:u:m:t:", \my %opts );

## Print audit usage message
    print audit_usage();

## Check if Help required
    if ( $opts{h} ) {

## Print audit help message
        print audit_help();
        
## Exit with status
        exit(0);
    }

## Open ACF
    my $acf = new AFX::ACF();

## Define variables for SITE_ID, UNITS, MACHINES, TEMPLATES, DAEMON
    my ( $site_id, @units, @machines, @templates, $daemon );

## Check is SITE_ID specified
    if ( $opts{s} ) {
        $site_id = uc( $opts{s} );
    }
    else {

## If Site'd Id not specified, default will be used
        $site_id = $acf->open_sitefile();
    }

## Print Audit started message
    audit_started( $acf, $site_id );

## Print version message
    print $acf->message_title() . "\n\n";

## Check is UNITS specified
    if ( $opts{u} ) {
        @units = split( /,/, uc( $opts{u} ) );
    }

## Check is MACHINES specified
    if ( $opts{m} ) {
        @machines = split( /,/, uc( $opts{m} ) );
    }

## Check is TEMPLATES specified
    if ( $opts{t} ) {
        @templates = split( /,/, $opts{t} );
    }

## Check is Daemon specified
    if ( $opts{d} ) {
        $daemon = lc( $opts{d} );
    }

## Set default debug mode
    my $debug = 0;

## Check if Debug mode specified
    if ( $opts{D} ) {
        $debug = 1;
    }

## Set default exclude mode
    my $exclude = 0;

## Check if Exclude mode specified
    if ( $opts{X} ) {
        $exclude = 1;
    }

## Set default noprompt mode
    my $noprompt = 0;

## Check if Noprompt mode specified
    if ( $opts{x} ) {
        $noprompt = 1;
    }

## Open ASF
    my $asf = new AFX::ASF( $acf, $site_id ) if $site_id;

## Exit with exception: ASF processing error
    if ( !$asf ) {

## Set Error status
        my $status = 1;

## Print Audit finished message
        audit_finished( $acf, $site_id, $status );

## Exit with status
        exit($status);
    }

## Update ASF using SMF
    $asf->parse_smf($noprompt);

## If Machines not specified
    if ( !@units and !@machines ) {

## Print no unit message
        message_no_unit($acf);

## Print units details
        $asf->show_units();

## Set Error status
        my $status = 1;

## Print Audit finished message
        audit_finished( $acf, $site_id, $status );

## Exit with status
        exit($status);
    }

## Create Process
    my $process = new AFX::Process( $acf, $asf, 'audit' );

## If process wasn't created
    if ( !$process ) {

## Print process failed message
        $acf->message_failed_process();

## Set Error status
        my $status = 1;

## Print Audit finished message
        audit_finished( $acf, $site_id, $status );

## Exit with status
        exit($status);
    }

## Add machine for processing
    $process->add_machine( \@units, \@machines );

## Set daemon mode
    if ($daemon) {
        $process->add_daemon($daemon);
        $process->set_noprompt();
    }

## Set noprompt mode if specified
    $process->set_noprompt() if $noprompt;

## Set debug mode if specified
    $process->set_debug() if $debug;

## Set exclude mode if specified
    $process->set_exclude() if $exclude;

## Set Error status
    my $status = 1;

## Execute Process
    if ( $process->execute( \@templates ) ) {

## Show ARF processing details,
        $status = $process->show_results();
    }

## Print Audit finished message
    audit_finished( $acf, $site_id, $status );

## Exit with status
    exit($status);

} ## end sub audit

##############################################################################
#
# audit_help()
#
# Message: Audit help
#
# Return:
# - logged message

sub audit_help {

## Set message
    my $message .= "\nFlags:";
    $message .= "\n-s SITE_ID:
    Identifies a site to be audited. Unique Site Identifier should follow -s option as an argument. Unique Site Identifier should be obtained as name of SITE_ID.master file(s). If not specified, then default value configured while config.pl used.";
    $message .= "\n-u MACH: 
    Identifies units to be audited. Argument is comma separated list of units. Example: SDP,UPM,etc. For all units list see TEST.master inside of the site folder.";
    $message .= "\n-m MACH_ID:
    Identifies machines to be audited. Argument is comma separated list of machines. Example: SDP1,SDP2,SLU5,etc. Machines list depends on site configuration and SITE_ID.master file created to audit the site.";
    $message .= "\n-t TEMPLATE:
    Identifies templates to be executed while running the audit. Argument is comma separated list of templates. This flag allows controlling which templates will be used while running the audit. Templates list should be obtained from template folder.";
    $message .= "\n-d daily/weekly:
    Identifies the mode audit will be executed. Argument has daily or weekly value. This flag allows executing audit steps marked either daily or weekly. By default audit will execute all steps in spite of markers.";
    $message .= "\n-D:
    Enables DEBUG mode";
    $message .= "\n-x:
    Enables noprompt mode";
    $message .= "\n-X:
    Suppress N/A within ARF\n";

## Return message
    return $message;

} ## end sub audit_help

##############################################################################
#
# audit_started()
#
# Message: Audit started
#
# Return:
# - logged message
#
# Arguments expected are:
# - acf        - ACF Object
# - site_id    - Site Id

sub audit_started {
    my ( $acf, $site_id ) = @_;

## Get time
    my $now = localtime;

## Set message
    my $message = "\n## Audit of $site_id started at $now ";
    $message .= "#" while ( length($message) < 70 );
    $message .= "\n";

## Return message
    return $acf->logging( $message, 1, 'audit' );

} ## end sub audit_started

##############################################################################
#
# audit_finished()
#
# Message: Audit finished
#
# Return:
# - logged message
#
# Arguments expected are:
# - acf        - ACF Object
# - site_id    - Site Id
# - status     - Process status

sub audit_finished {
    my ( $acf, $site_id, $status ) = @_;

## Get time
    my $now = localtime;

## Set message
    my $message = "\n## Audit of $site_id finished at $now ";
    $message .= "#" while ( length($message) < 70 );
    $message .= "\n";

## Show Status
    $message .= "STATUS=$status\n";

## If status is failed
    if ($status) {
        $message .=
          "INFO=Audit done with failed parameters or processing errors\n";
    }
    else {
        $message .= "INFO=No issues detected during audit\n";
    }

## Return message
    return $acf->logging( $message, 1, 'audit' );

} ## end sub audit_finished

##############################################################################
#
# audit_usage()
#
# Message: Audit usage
#
# Return:
# - logged message

sub audit_usage {

## Set message
    my $message =
"Usage: [perl] audit.pl [-s {SITE_ID}] [-u {MACH}] [-m {MACH_ID}] [-t {TEMPLATE}] [-d {daily|weekly}] [-D] [-X] [-x]";
    $message .= "\nHelp: [perl] audit.pl -h\n";

## Return message
    return $message;

} ## end sub audit_usage

##############################################################################
#
# message_no_unit()
#
# Message: No MACH specified.
#
# Return:
# - logged message
#
# Arguments expected are:
# - acf      - ACF Object

sub message_no_unit {
    my ($acf) = @_;

## Set message
    my $message = "Error: MACH or MACH_ID not specified.\n";
    $message .= "Please specify units or machines which will be audited.";

## Return message
    return $acf->logging( $message, 1, 'audit' );

} ## end sub message_no_unit
